package main

import (
	"bufio"
	"bytes"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"sync"
	"time"
)

const (
	textBlack = iota + 30
	textRed
	textGreen
	textYellow
	textBlue
	textPurple
	textCyan
	textWhite
)

func Red2(str string) string {
	return textColor2(textRed, str)
}
func Yellow2(str string) string {
	return textColor2(textYellow, str)
}
func Green2(str string) string {
	return textColor2(textGreen, str)
}



func textColor2(color int, str string) string {
	return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", color, str)
}






type Order_ctl struct{
	Errmsg string  `json:"errmsg"`
	Goods []Good_ctl `json:"good"`
}

type Good_ctl struct{
	GoodsName string `json:"goods_name"`
	Goodsstatus string `json:"goods_status"`
}

type Order2_ctl struct{
	Errmsg string  `json:"errmsg"`
	Goods []Good2_ctl `json:"good"`
}

type Good2_ctl struct {
	GoodsName string `json:"goods_name"`
	Hostname  string `json:"Hostname"`
	Core    int    `json:"core"`
	Cpuname string `json:"cpuname"`
	TotalMem string `json:"total_mem"`
	Platform        string `json:"platform"`
	PlatformVersion string `json:"PlatformVersion"`
	Os              string `json:"Os"`
	KernelVersion   string `json:"KernelVersion"`
	Status          string `json:"status"`
}

type BOrder struct{
	Errmsg string  `json:"errmsg"`
	Goods []BGood `json:"good"`
}

type BGood struct{
	GoodsName string `json:"goods_name"`
	GoodsIp string `json:"goods_ip"`
	Goodsstatus string `json:"goods_status"`
	Goodsinfo string `json:"goods_info"`
	Goodstime string `json:"goods_time"`
}

func Getallnode(g string) {
	//fmt.Printf("192.168.159.146\t      Status")
	fmt.Println("IP            .\t      Status          .Group")
	url := apiaddress + "/getallnode"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	allinfos := &Order_ctl{}
	errjson := json.Unmarshal(body,allinfos)
	if errjson != nil{
		fmt.Println(err)
	}
	for _,x := range append(allinfos.Goods,Good_ctl{}){
		ip := x.GoodsName
		if len(ip) == 0 {
			continue
		}
		group := getipgroup(ip)

		if len(g) != 0 {
			if group != g {
				continue
			}
		}

		status := x.Goodsstatus
		if status == "OK"{

			fmt.Printf("%v\t%v%v%v%v%v%v\n",ip," "," ","    ",Green2(status),"              ",group)
		}else {
			fmt.Printf("%v\t%v%v%v%v%v%v\n",ip," "," ","    ",Red2(status),"         ",group)
		}
	}
}


func Getonenode(oneip string) {
	//fmt.Printf("192.168.159.146\t      Status")
	fmt.Println("IP            .\t      Status:for one        .Group")
	url := apiaddress + "/getallnode"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	allinfos := &Order_ctl{}
	errjson := json.Unmarshal(body,allinfos)
	if errjson != nil{
		fmt.Println(err)
	}
	var tag int
	for _,x := range append(allinfos.Goods,Good_ctl{}){
		ip := x.GoodsName
		group := getipgroup(ip)
		status := x.Goodsstatus
		if ip == oneip {
			if status == "OK"{
				fmt.Printf("%v\t%v%v%v%v%v%v\n",ip," "," ","    ",Green2(status),"              ",group)
			}else {
				fmt.Printf("%v\t%v%v%v%v%v%v\n",ip," "," ","    ",Red2(status),"         ",group)
			}
			tag = 2
		}
	}
	if tag != 2 {
		fmt.Println("Not Found your server: ",oneip)
		os.Exit(0)
	}
}

func Getallinfos(lei string,oneip string) {

	url := apiaddress + "/cmdblist"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	allinfos_re := &Order2_ctl{}
	errjson := json.Unmarshal(body,allinfos_re)
	if errjson != nil{
		fmt.Println("Run cmdberr:",errjson)
	}
	var tag2 int
	if lei == "all" {
		for _, x := range append(allinfos_re.Goods, Good2_ctl{}) {
			ip := x.GoodsName
			if len(ip) == 0 {
				continue
			}
			hostname := x.Hostname
			core := x.Core
			cpuname := x.Cpuname
			mem := x.TotalMem
			osversion := x.Os + ":" + x.Platform + x.PlatformVersion + " Kernel:" + x.KernelVersion
			status := x.Status
			group := getipgroup(ip)
			fmt.Println(ip, "   ", hostname)
			fmt.Println("---", "Core:", core)
			fmt.Println("      ", "Cpuname:", cpuname)
			fmt.Println("      ", "Toatlmem:", mem)
			fmt.Println("      ", "Osinfos:", osversion)
			if status == "OK" {
				fmt.Println("      ", "Status:", Green2(status))
			} else {
				fmt.Println("      ", "Status:", Red2(status))
			}
			fmt.Println("      ", "Group:", group)
			fmt.Println(" ")
		}
	}else {
		for _, x := range append(allinfos_re.Goods, Good2_ctl{}) {
			ip := x.GoodsName
			if len(ip) == 0 {
				continue
			}
			hostname := x.Hostname
			core := x.Core
			cpuname := x.Cpuname
			mem := x.TotalMem
			osversion := x.Os + ":" + x.Platform + x.PlatformVersion + " Kernel:" + x.KernelVersion
			status := x.Status
			group := getipgroup(ip)
			if ip == oneip {
				fmt.Println(ip, "   ", hostname)
				fmt.Println("---", "Core:", core)
				fmt.Println("      ", "Cpuname:", cpuname)
				fmt.Println("      ", "Toatlmem:", mem)
				fmt.Println("      ", "Osinfos:", osversion)
				if status == "OK" {
					fmt.Println("      ", "Status:", Green2(status))
				} else {
					fmt.Println("      ", "Status:", Red2(status))
				}
				fmt.Println("      ", "Group:", group)
				fmt.Println(" ")
				tag2 = 2
			}
		}
		if tag2 != 2 {
			fmt.Println("Not Found your server: ",oneip)
		}
	}
}

func listenlist() {

	url := apiaddress +"/listenlist"
	method := "GET"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	var listenst = &BOrder{}
    errjson := json.Unmarshal(body,listenst)
    if errjson != nil{
    	fmt.Println("Run listenlisterr:",errjson)
	}
	for _,x := range append(listenst.Goods,BGood{}){
		name :=x.GoodsName
		ip := x.GoodsIp
		if len(ip) == 0 {
			continue
		}
		status := x.Goodsstatus
		checktime := x.Goodstime
		infos := x.Goodsinfo
		fmt.Println(ip, "   ", )
		fmt.Println("---", "Name:",name)
		fmt.Println("      ", "Infos:", infos)
		fmt.Println("      ", "CheckTime:", checktime)
		if status == "OK" {
			fmt.Println("      ", "Status:", Green2(status))
		} else {
			fmt.Println("      ", "Status:", Red2(status))
		}
		fmt.Println("")
	}
}

func makelisten(oneip string,ltype string,lname string,startcmd string,elseinfo string) {

	url := apiaddress +"/makelisten"
	method := "POST"
	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ip", oneip)
	_ = writer.WriteField("ltype", ltype)
	_ = writer.WriteField("lname", lname)
	_ = writer.WriteField("else", elseinfo)
	_ = writer.WriteField("startcmd", startcmd)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}
	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	 _ , err = ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	listenlist()
}

func updatenode(oneip string,urlme string) {

	url := urlme
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ip",oneip)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}
	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	_, err = ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Add node:",oneip)
	Getallnode("")
}

type userlist struct{
	Errmsg string  `json:"errmsg"`
	Goods []userlist_from `json:"good"`
}

type userlist_from struct{
	Logname string `json:"logname"`
}

func getloglist(oneip string){
	Getonenode(oneip)
	url := apiaddress + "/getreplaylog"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ip", oneip)
	_ = writer.WriteField("filename", "pac-1000-2022-06-03.log")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	userlists := &userlist{}
	errjson := json.Unmarshal(body,userlists)
	if errjson != nil{
		fmt.Println("run getrepalyerr:",errjson)
	}

	fmt.Println("---", "List:")
	for _,x := range append(userlists.Goods,userlist_from{}){
		filename := x.Logname
		if len(filename) == 0 {
			continue
		}
		fmt.Println("      ", "Logname: ",filename)
		fmt.Println("")

	}

}

func mkdir(path string) {

	_ = os.Mkdir(path, 0700)

}

const ShellToUse = "bash"
func shellbywhileout (cmdstring string){ //可以执行加密后的非playbook ansible命令
	cmd := exec.Command(ShellToUse, "-c",cmdstring)
	stdout, _ := cmd.StdoutPipe() //正确输出
	cmd.Stderr = cmd.Stdout //错误重定向
	err := cmd.Start()
	reader := bufio.NewReader(stdout)
	for {
		line, err2 := reader.ReadString('\n')
		if err2 != nil || io.EOF == err2 {
			break
		}

		fmt.Printf("%v",line)
		if err != nil{
			fmt.Println(err)
		}
	}


	if err != nil{
		fmt.Println(err)
	}
	cmd.Wait()
}

func downloadtwofile(oneip string,filenamedown string){
	var body string
	mkdirpath := "/etc/replay/logfile/" + oneip
	mkdir(mkdirpath)
	file := strings.Split(filenamedown,".")
	dataname := file[0] + ".data"
	fmt.Println("Download history:",Yellow2(filenamedown))
	body = downloadreplaylogforacthion(oneip,filenamedown)
	pathlog := "/etc/replay/logfile/" + oneip + "/" +filenamedown
	writefile_ctl(pathlog,body)
	fmt.Println("Download history:",Yellow2(dataname))
	pathdata := "/etc/replay/logfile/" + oneip + "/" +dataname
	body = downloadreplaylogforacthion(oneip,dataname)
	writefile_ctl(pathdata,body)

	fmt.Println(Yellow2("Start playback:(等待解析操作日志)"),Red2(filenamedown))
	cmdstring := "replayaction " + pathdata + " "  + pathlog
	fmt.Println("You also can Run This shell to playback:",cmdstring)
	fmt.Println("")
	fmt.Println("")
	time.Sleep(time.Second * 3)
	shellbywhileout(cmdstring)
}

func downloadreplaylogforacthion(oneip string,filenamea string)string{

	url := apiaddress + "/downloadreplaylog"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ip", oneip)
	_ = writer.WriteField("filename", filenamea)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)

	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)

	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)

	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)

	}
	return string(body)
}

type loading struct {
	Cpuload float32 `json:"Cpuload"`
	Ip      string  `json:"Ip"`
	Membfb  float64 `json:"Membfb"`
	Status  string  `json:"Status"`
}

func forgetload(oneip string){
	for {
		cpuload,memload,status := getload(oneip)
		if status == "OK" {
			fmt.Printf(" %v Cpu: %v%%    Mem: %v%%      Status: %v  %v\r", oneip, cpuload, memload, Green2(status),"  ")
		}else {
			fmt.Printf(" %v Cpu: %v%%    Mem: %v%%      Status: %v  %v\r", oneip, cpuload, memload, Red2(status), "   ")
		}
		time.Sleep(time.Second)
	}
}

func getload(oneip string)(float32,float64,string){
	url := apiaddress + "/getnode"
	method := "POST"
	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ip", oneip)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)

	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)

	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)

	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)

	}

	loadings := &loading{}

	errjson := json.Unmarshal(body,loadings)
	if errjson != nil {
		fmt.Println("Run loading err: Can't conection")
		os.Exit(0)
	}

	cpuload := loadings.Cpuload
	memload := loadings.Membfb
	status := loadings.Status
    return cpuload,memload,status
}

type delcmdb_return struct {
	Err int    `json:"err"`
	Msg string `json:"msg"`
}

func delcmdb(oneip string){
	url := apiaddress + "/delcmdb"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ip", oneip)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	delcmdb_returns := &delcmdb_return{}
	errjson := json.Unmarshal(body,delcmdb_returns)
	if errjson != nil{
		fmt.Println("Run delcmdb err")
	}

	msg := delcmdb_returns.Msg
	if msg ==  "success"{
		//Getallinfos("all","all")
		fmt.Println("Del ",Green2(oneip),"Success from cmdb !")
	}else {
		fmt.Println("Del cmdb no found:",Red2(oneip))
	}

}

func dellisten(oneip string ,listenname string){

	url := apiaddress + "/dellisten"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("name", listenname)
	_ = writer.WriteField("ip", oneip)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	delcmdb_returns := &delcmdb_return{}
	errjson := json.Unmarshal(body,delcmdb_returns)
	if errjson != nil{
		fmt.Println("Run delcmdb err")
	}

	msg := delcmdb_returns.Msg
	if msg ==  "success"{
		//Getallinfos("all","all")
		fmt.Println("Del ",Green2(oneip),Green2(listenname),"Success from listenlist !")
	}else {
		fmt.Println("Del listenlist no found:",Red2(oneip),Red2(listenname))
	}
}

func checkin(oneip string){
	//fmt.Printf("192.168.159.146\t      Status")
	url := apiaddress + "/getallnode"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	allinfos := &Order_ctl{}
	errjson := json.Unmarshal(body,allinfos)
	if errjson != nil{
		fmt.Println(err)
	}
	var tag int
	for _,x := range append(allinfos.Goods,Good_ctl{}){
		ip := x.GoodsName
		status := x.Goodsstatus
		if ip == oneip && status == "OK"{
			tag =2
		}
	}
	if tag != 2 {
		fmt.Println("Not Found or node is notOK :",Red2(oneip),"Can't do next Step.")
		os.Exit(0)
	}
}

func checkin3(oneip string)string{
	url := apiaddress + "/getallnode"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)

	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)

	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)

	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)

	}
	allinfos := &Order_ctl{}
	errjson := json.Unmarshal(body,allinfos)
	if errjson != nil{
		fmt.Println(err)
	}
	var tag int
	for _,x := range append(allinfos.Goods,Good_ctl{}){
		ip := x.GoodsName
		status := x.Goodsstatus
		if ip == oneip && status == "OK"{
			tag =2
			return "OK"
		}
	}
	if tag != 2 {
		fmt.Println("Not Found or node is notOK :",Red2(oneip),"Can't do next Step.")
		return "NO"

	}
	return "NO"

}

func checkin2(oneip string){
	//fmt.Printf("192.168.159.146\t      Status")
	url := apiaddress + "/getallnode"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	allinfos := &Order_ctl{}
	errjson := json.Unmarshal(body,allinfos)
	if errjson != nil{
		fmt.Println(err)
	}
	var tag int
	for _,x := range append(allinfos.Goods,Good_ctl{}){
		ip := x.GoodsName

		if ip == oneip {
			tag =2
		}
	}
	if tag != 2 {
		fmt.Println("Not Found or node is notOK :",Red2(oneip),"Can't do next Step.")
		os.Exit(0)
	}
}

func getport() (string,bool) {
	conn := os.Getenv("Apiport")
	if conn == "" {
		return conn,false
	}
	return conn,true
}
var apiaddress string


func cmdbupdate(){

	url := apiaddress +  "/cmdbupdate"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	_, err = ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(Green2("  Cmdb Update Success !"))
}

type shelljson struct {
	Code       int    `json:"code"`
	Msg        string `json:"msg"`
	ReturnCode int    `json:"return_code"`
}

const (

	base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

)

var coder = base64.NewEncoding(base64Table)



func jiami(src []byte) []byte {

	return []byte(coder.EncodeToString(src))

}

func shelllong(oneip,shell string){
	url :=  apiaddress + "/lrangeshell"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	_ = writer.WriteField("ip", oneip)
	_ = writer.WriteField("shell", shell)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)

	fmt.Println(Yellow2(oneip), " Result: ")
	if err != nil {
		fmt.Println(err)
		return
	}
	shelljsons := &shelljson{}

	errjosn := json.Unmarshal(body,shelljsons)
	if errjosn != nil{
		fmt.Println("Run shell err")
	}

	if shelljsons.ReturnCode == 0 {
		shellreturn := shelljsons.Msg
		fmt.Println(Green2(shellreturn))
		fmt.Println(" ")
	}else {
		shellreturn := shelljsons.Msg
		code := shelljsons.ReturnCode
		str := strconv.Itoa(code)
		fmt.Println(Red2(shellreturn),"\n","     ",Red2("Return_code:"),Red2(str),"\n","     ",Red2("retrun_cdoe not good,please try later."))
		fmt.Println(" ")
	}
}

func shelllong2(oneip,shell string){
	gloadb_shell_id ++
	url :=  apiaddress + "/lrangeshell"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	_ = writer.WriteField("ip", oneip)
	_ = writer.WriteField("shell", shell)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)

	fmt.Println(Yellow2(oneip), " Result: ")
	if err != nil {
		fmt.Println(err)
		return
	}
	shelljsons := &shelljson{}

	errjosn := json.Unmarshal(body,shelljsons)
	if errjosn != nil{
		fmt.Println("Run shell err")
	}

	if shelljsons.ReturnCode == 0 {
		shellreturn := shelljsons.Msg
		fmt.Println(Green2(shellreturn))
		fmt.Println(" ")
		wg.Done()
	}else {
		shellreturn := shelljsons.Msg
		code := shelljsons.ReturnCode
		str := strconv.Itoa(code)
		fmt.Println(Red2(shellreturn),"\n","     ",Red2("Return_code:"),Red2(str),"\n","     ",Red2("retrun_cdoe not good,please try later."))
		fmt.Println(" ")
		wg.Done()
	}

}

type getipgroupjson struct {
	Code  int    `json:"code"`
	Group string `json:"group"`
	Ip    string `json:"ip"`
}
func getipgroup(oneip string)string{

	url := "http://127.0.0.1:5001/nodegroup"
	method := "GET"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	_ = writer.WriteField("ip", oneip)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)

	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)

	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)

	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)

	}
	getipgroupjsons := &getipgroupjson{}

	errjson := json.Unmarshal(body,getipgroupjsons)
	if errjson != nil {
		fmt.Println("run groupfind err")
		return "none"
	}

	group := getipgroupjsons.Group
	if group != "no found in list"{
		return group
	}else {
		return "none"
	}
}

type addnodeintogroupjson struct {
	Code  int    `json:"code"`
	Group string `json:"group"`
}
func addnodeintogroup(oneip,group string){

	url := apiaddress +"/addnodeintogroup"
	method := "GET"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	_ = writer.WriteField("ip", oneip)
	_ = writer.WriteField("group", group)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	addnodeintogroupjsons := &addnodeintogroupjson{}

	errjosn := json.Unmarshal(body,addnodeintogroupjsons)
	if errjosn != nil {
		fmt.Println("Run addnodeintogroup err")
	}
	returninfo := addnodeintogroupjsons.Group
		fmt.Println("Add: ",oneip,"Into: ",group," [INFO]:",returninfo)

}


func delnodefromgroip(oneip,group string){

	url := apiaddress + "/delnodefromgroup"
	method := "GET"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	_ = writer.WriteField("ckey", "na912nkdKO0q2nausbAQ10naslpjams")
	_ = writer.WriteField("ip", oneip)
	_ = writer.WriteField("group", group)
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	delnodeintogroupjsons := &addnodeintogroupjson{}

	errjosn := json.Unmarshal(body,delnodeintogroupjsons)
	if errjosn != nil {
		fmt.Println("Run delnodeintogroup err")
	}
	returninfo := delnodeintogroupjsons.Group
	fmt.Println("Del: ",oneip,"Into: ",group," [INFO]:",returninfo)
}

func Read_file(filname string)  (string){
	f, err := ioutil.ReadFile(filname)
	if err != nil {
		fmt.Println("read fail", err)
	}
	return string(f)
}

type hostsjson struct {
	Hostlist   []hosts `json:"hostlist"`
}

type hosts struct {
Ip   string `json:"ip"`
}

var gloadb_shell_id = 0
var wg sync.WaitGroup

//func fileip(fn string,sh string) {
//
//	for {
//		wg.Add(1)
//		time.Sleep(time.Millisecond * 10)
//			//go soc(line, sh)
//	}
//	wg.Done()
//	wg.Wait()
//	os.Exit(1)
//}

func shellproint(){

}

func hostsfileindex(filename string,group string,shell string) {

	file, err := os.Open(filename)
	if err != nil {
		log.Fatalf("Error when opening file: %s", err)
	}
	fileScanner := bufio.NewScanner(file)
	var hostsjsons  hostsjson
	for fileScanner.Scan() {

		if len(fileScanner.Text()) == 0 {
			continue
		}
		time.Sleep(time.Millisecond * 10)

		index := strings.Index(fileScanner.Text(),group)
		if index != -1{
			wg.Add(1)
			ip := strings.Split(fileScanner.Text(),":")
			hostsjsons.Hostlist =append(hostsjsons.Hostlist,hosts{Ip: ip[0]})
			info := checkin3(ip[0])
			if info == "OK" {
				go shelllong2(ip[0], shell)
				fmt.Println(" ")
			}else {
				fmt.Println(" ")
				wg.Done()
			}
		}
	}
	wg.Wait()
	os.Exit(0)
}


func main(){
	port,err := getport()
	if !(err) {
		fmt.Println("Can't find  'Apiport' in ENV. Can't conect to Server.")
		os.Exit(-1)
	}else {
		apiaddress = "http://127.0.0.1:" + port
	}

	var get string
	flag.StringVar(&get, "get", "", "get node/status/info/listenlist all")

	var i string
	flag.StringVar(&i, "i", "", "one server")

	var make string
	flag.StringVar(&make, "make", "", "make listenps")

	var listenname string
	flag.StringVar(&listenname, "listenname", "", "Listenname for run")

	var startcmd string
	flag.StringVar(&startcmd, "startcmd", "", "restart if bad")

	var types string
	flag.StringVar(&types, "types", "", "type for os")

	var psname string
	flag.StringVar(&psname, "psname", "", "grep by this in pspool")

	var del string
	flag.StringVar(&del, "del", "", "del something")

	var add string
	flag.StringVar(&add, "add", "", "add something")

	var filename string
	flag.StringVar(&filename, "filename", "", "filename of replay")

	var v string
	flag.StringVar(&v,"v","", "version")

	var m string
	flag.StringVar(&m,"m","", "mod")

	var a string
	flag.StringVar(&a,"a","", "cs")

	var g string
	flag.StringVar(&g,"g","", "grep group")

	var p string
	flag.StringVar(&p,"p","", "pi liang")


	flag.Parse()

	checkapi()

	if len(m) != 0 && len(i) !=0 && len(a) != 0 && len(p) == 0{
		checkin(i)
		cmd := jiami([]byte(a))
		shelllong(i,string(cmd))
	}else if  len(m) != 0  && len(p) != 0 && len(a) !=0{
		cmd := jiami([]byte(a))
		hostsfileindex(filename,g,string(cmd))
	}

	if len(v) != 0 && v == "version"{
		fmt.Println("LIP-0.2.05-Ctl.Use to Call ffs server.")
	}

	if len(get) != 0{
		if get == "node"  && len(i) == 0 && len(g) == 0{
			Getallnode("")
		}else if get == "node"  && len(i) == 0 && len(g) != 0 {
			Getallnode(g)
		}else if get == "node" && len(i) != 0{
			Getonenode(i)
		}else if get == "cmdb" && len(i) == 0 {
			Getallinfos("all","all")
		}else if get == "cmdb"  && len(i) != 0{
			Getallinfos("one",i)
		} else if get == "listen" && len(i) == 0{
			listenlist()
		}else if get == "replay" && len(i) != 0{
			getloglist(i)
		} else if get == "loading" && len(i) != 0{
			forgetload(i)
		} else  if get == "api"{
			checkapi2()
		}else{
			fmt.Println("-> Get Can't resolving: ",Yellow2(get))
		}
	}

	if len(make) != 0{
		if make == "listen" && len(listenname) != 0 && len(startcmd) != 0 && len(types) != 0 && len(psname) != 0 && len(i) != 0{
			checkin(i)
			makelisten(i,types,psname,startcmd,listenname)

		}else  if make == "action" && len(i) != 0 && len(filename) != 0{ //下载文件
			checkin(i)
			downloadtwofile(i,filename)
		} else if make == "update" {
			cmdbupdate()
		}else {
			fmt.Println("-> Make Can't resolving: ",get,listenname,startcmd,types,psname)
		}
  	}

  	if len(del) != 0{
  		if del == "node" && len(i) != 0{
			checkin2(i)
			url := apiaddress + "/delnode"
			updatenode(i,url)
		}else if del == "cmdb" &&len(i) != 0{
			checkin2(i)
			delcmdb(i)
		}else if del == "listen" && len (i) !=0 && len(listenname) != 0{
			checkin2(i)
			dellisten(i,listenname)
		} else if del == "into" && len(i) != 0  {
			if len(g) == 0{
				fmt.Println("Choose Group! : -g groupname")
				os.Exit(-1)
			}
			checkin2(i)
			delnodefromgroip(i,g)
		}else {
			fmt.Println("--> Del Can't resolving:",del,i)
		}
	}

	if len(add) != 0{
		if add == "node" && len(i) != 0{
			url := apiaddress + "/addnode"
			updatenode(i,url)
			fmt.Println(Yellow2("New node will be join in next check"))
		}else if add == "into" && len(i) !=0{
			if len(g) == 0{
				fmt.Println("Choose Group! : -g groupname")
				os.Exit(-1)
			}
			checkin2(i)
			addnodeintogroup(i,g)
		}else {
			fmt.Println("--> Add Can't resolving: -add -i",add,i)
		}
	}
}


func writefile_ctl(filename string,nei string) error{
	fileName := filename
	f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		fmt.Println("file create failed. err: " + err.Error())
	} else {

		content := nei
		n, _ := f.Seek(0, os.SEEK_END)
		_, err = f.WriteAt([]byte(content), n)

		defer f.Close()
	}
	return err
}

type alivejson struct {
	Err int    `json:"err"`
	Msg string `json:"msg"`
}

func checkapi(){
	status := alive()
	if status == "OK"{
		fmt.Println(Green2("."))
	}else {
		fmt.Println("Api server Run:",Red2(status))
		os.Exit(-1)
	}
}

func checkapi2(){
	status := alive()
	if status == "OK"{
		fmt.Println("-- \n  -Api server Run:",Green2(status),"\n")
	}else {
		fmt.Println("-- \n  -Api server Run:",Red2(status),"\n")
		os.Exit(-1)
	}
}


func alive() string{


	url := apiaddress + "/api"
	method := "GET"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	err := writer.Close()
	if err != nil {
	}


	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println("Api can't conect")

	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println("\nApi server Run:",Red2("bad"),"\n")
		os.Exit(-1)

	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
	}
	alivejsons := & alivejson{}

	errjson := json.Unmarshal(body,alivejsons)
	if errjson != nil{
		fmt.Println("Apiserver may not ok")
	}

	status := alivejsons.Msg
	if status == "success"{
		return "OK"
	}else {
		return  "bad"
	}
}
